#ifndef NOEUDVISITOR_H_
#define NOEUDVISITOR_H_

#include <vector>
#include <iostream>
#include <iomanip>
using namespace std;

/* Specification des metode visiteur qui permet d'evaluer
 *  une structure (Une metode pour chaque type de noeud */
class NoeudSeqInst;
class NoeudPour;
class NoeudSi;
class NoeudTantQue;
class NoeudRepeter;
class NoeudAffectation;
class NoeudDeclaration;
class NoeudEcrire;
class NoeudLire;
class NoeudOperateurBinaire;
class SymboleValue;

/* Classe abstraite du visitor, mere de tout les visiteurs
 *  (afficher, evaluation, transphormation ...) */
class NoeudVisitor {
public:
    NoeudVisitor();
    virtual ~NoeudVisitor();
    virtual void VisitNoeudSeqInst(NoeudSeqInst*);
    virtual void VisitNoeudPour(NoeudPour*);
    virtual void VisitNoeudSi(NoeudSi*);
    virtual void VisitNoeudTantQue(NoeudTantQue*);
    virtual void VisitNoeudRepeter(NoeudRepeter*);
    virtual void VisitNoeudAffectation(NoeudAffectation*);
    virtual void VisitNoeudDeclaration(NoeudDeclaration*);
    virtual void VisitNoeudEcrire(NoeudEcrire*);
    virtual void VisitNoeudLire(NoeudLire*);
    virtual void VisitNoeudOperateurBinaire(NoeudOperateurBinaire*);
    virtual void VisitSymboleValue(SymboleValue*);
    virtual inline void IncresIndentation() { }
    virtual inline void DecresIndentation() { }

};

class AfficherVisitor : public NoeudVisitor  {
public:
    AfficherVisitor();
//   virtual ~AfficherVisitor() {}
    virtual void afficherIndentation() {
        cout << setw(4*indentation) << " ";
    }
    inline void IncresIndentation() {
        indentation ++;
    }
    inline void DecresIndentation() {
        indentation --;
    }
    virtual void VisitNoeudSeqInst(NoeudSeqInst*);
    virtual void VisitNoeudPour(NoeudPour*);
    virtual void VisitNoeudSi(NoeudSi*);
    virtual void VisitNoeudTantQue(NoeudTantQue*);
    virtual void VisitNoeudRepeter(NoeudRepeter*);
    virtual void VisitNoeudAffectation(NoeudAffectation*);
    virtual void VisitNoeudDeclaration(NoeudDeclaration*);
    virtual void VisitNoeudEcrire(NoeudEcrire*);
    virtual void VisitNoeudLire(NoeudLire*);
    virtual void VisitNoeudOperateurBinaire(NoeudOperateurBinaire* e);
    virtual void VisitSymboleValue(SymboleValue*);
private:
    int indentation;
};


class TypeVisitor : public NoeudVisitor  {
public:
	TypeVisitor();
    virtual void VisitNoeudSeqInst(NoeudSeqInst*);
    virtual void VisitNoeudPour(NoeudPour*);
    virtual void VisitNoeudSi(NoeudSi*);
    virtual void VisitNoeudTantQue(NoeudTantQue*);
    virtual void VisitNoeudRepeter(NoeudRepeter*);
    virtual void VisitNoeudAffectation(NoeudAffectation*);
    virtual void VisitNoeudDeclaration(NoeudDeclaration*);
    virtual void VisitNoeudEcrire(NoeudEcrire*);
    virtual void VisitNoeudLire(NoeudLire*);
    virtual void VisitNoeudOperateurBinaire(NoeudOperateurBinaire* e);
    virtual void VisitSymboleValue(SymboleValue*);
};

#endif
